{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Tce3stUlHN0L"
      },
      "source": [
        "##### Copyright 2024 Google LLC."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "tuOe1ymfHZPu"
      },
      "outputs": [],
      "source": [
        "# @title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "PXNm5_p_oxMF"
      },
      "source": [
        "This is a quick demo of Gemma running on KerasNLP.\n",
        "\n",
        "Note that you will need a large GPU (e.g. A100) to run this as well.\n",
        "\n",
        "General Keras reading:\n",
        "- [Getting started with Keras](https://keras.io/getting_started/)\n",
        "- [Getting started with KerasNLP](https://keras.io/guides/keras_nlp/getting_started/)\n",
        "\n",
        "<table align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/google-gemini/gemma-cookbook/blob/main/Gemma/Keras_Gemma_2_Quickstart_Chat.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Run in Google Colab</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VzFhJDayXroT"
      },
      "source": [
        "## Access"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "id": "DrBoa_Urw9Vx"
      },
      "outputs": [],
      "source": [
        "import os\n",
        "from google.colab import userdata\n",
        "\n",
        "os.environ[\"KAGGLE_USERNAME\"] = userdata.get('KAGGLE_USERNAME')\n",
        "os.environ[\"KAGGLE_KEY\"] = userdata.get('KAGGLE_KEY')\n",
        "\n",
        "os.environ[\"KERAS_BACKEND\"] = \"jax\"  # Or \"tensorflow\" or \"torch\"."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "z9oy3QUmXtSd"
      },
      "source": [
        "## Installation"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "UehUHTaZmK0n"
      },
      "outputs": [],
      "source": [
        "# Install all deps\n",
        "!pip install -U keras-nlp\n",
        "!pip install -U keras==3.3.3"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FX47AUYrXwLK"
      },
      "source": [
        "## Quickstart"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {
        "id": "yygIK9DEIldp"
      },
      "outputs": [
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "Downloading from https://www.kaggle.com/api/v1/models/keras/gemma2/keras/gemma2_instruct_9b_en/1/download/model.safetensors...\n",
            "Downloading from https://www.kaggle.com/api/v1/models/keras/gemma2/keras/gemma2_instruct_9b_en/1/download/model.safetensors.index.json...\n",
            "Downloading from https://www.kaggle.com/api/v1/models/keras/gemma2/keras/gemma2_instruct_9b_en/1/download/metadata.json...\n",
            "100%|██████████| 143/143 [00:00<00:00, 209kB/s]\n",
            "Downloading from https://www.kaggle.com/api/v1/models/keras/gemma2/keras/gemma2_instruct_9b_en/1/download/task.json...\n",
            "Downloading from https://www.kaggle.com/api/v1/models/keras/gemma2/keras/gemma2_instruct_9b_en/1/download/config.json...\n",
            "100%|██████████| 780/780 [00:00<00:00, 1.18MB/s]\n",
            "Downloading from https://www.kaggle.com/api/v1/models/keras/gemma2/keras/gemma2_instruct_9b_en/1/download/model.safetensors...\n",
            "Downloading from https://www.kaggle.com/api/v1/models/keras/gemma2/keras/gemma2_instruct_9b_en/1/download/model.safetensors.index.json...\n",
            "Downloading from https://www.kaggle.com/api/v1/models/keras/gemma2/keras/gemma2_instruct_9b_en/1/download/model.weights.h5...\n",
            "100%|██████████| 17.2G/17.2G [02:41<00:00, 114MB/s]\n",
            "Downloading from https://www.kaggle.com/api/v1/models/keras/gemma2/keras/gemma2_instruct_9b_en/1/download/model.safetensors...\n",
            "Downloading from https://www.kaggle.com/api/v1/models/keras/gemma2/keras/gemma2_instruct_9b_en/1/download/model.safetensors.index.json...\n",
            "Downloading from https://www.kaggle.com/api/v1/models/keras/gemma2/keras/gemma2_instruct_9b_en/1/download/preprocessor.json...\n",
            "Downloading from https://www.kaggle.com/api/v1/models/keras/gemma2/keras/gemma2_instruct_9b_en/1/download/tokenizer.json...\n",
            "100%|██████████| 315/315 [00:00<00:00, 500kB/s]\n",
            "Downloading from https://www.kaggle.com/api/v1/models/keras/gemma2/keras/gemma2_instruct_9b_en/1/download/assets/tokenizer/vocabulary.spm...\n",
            "100%|██████████| 4.04M/4.04M [00:00<00:00, 16.9MB/s]\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">Preprocessor: \"gemma_causal_lm_preprocessor\"</span>\n",
              "</pre>\n"
            ],
            "text/plain": [
              "\u001b[1mPreprocessor: \"gemma_causal_lm_preprocessor\"\u001b[0m\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n",
              "┃<span style=\"font-weight: bold\"> Tokenizer (type)                                   </span>┃<span style=\"font-weight: bold\">                                             Vocab # </span>┃\n",
              "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩\n",
              "│ gemma_tokenizer (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">GemmaTokenizer</span>)                   │                                             <span style=\"color: #00af00; text-decoration-color: #00af00\">256,000</span> │\n",
              "└────────────────────────────────────────────────────┴─────────────────────────────────────────────────────┘\n",
              "</pre>\n"
            ],
            "text/plain": [
              "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n",
              "┃\u001b[1m \u001b[0m\u001b[1mTokenizer (type)                                  \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m                                            Vocab #\u001b[0m\u001b[1m \u001b[0m┃\n",
              "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩\n",
              "│ gemma_tokenizer (\u001b[38;5;33mGemmaTokenizer\u001b[0m)                   │                                             \u001b[38;5;34m256,000\u001b[0m │\n",
              "└────────────────────────────────────────────────────┴─────────────────────────────────────────────────────┘\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">Model: \"gemma_causal_lm\"</span>\n",
              "</pre>\n"
            ],
            "text/plain": [
              "\u001b[1mModel: \"gemma_causal_lm\"\u001b[0m\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n",
              "┃<span style=\"font-weight: bold\"> Layer (type)                  </span>┃<span style=\"font-weight: bold\"> Output Shape              </span>┃<span style=\"font-weight: bold\">         Param # </span>┃<span style=\"font-weight: bold\"> Connected to               </span>┃\n",
              "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩\n",
              "│ padding_mask (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">InputLayer</span>)     │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>)              │               <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ -                          │\n",
              "├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤\n",
              "│ token_ids (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">InputLayer</span>)        │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>)              │               <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ -                          │\n",
              "├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤\n",
              "│ gemma_backbone                │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">3584</span>)        │   <span style=\"color: #00af00; text-decoration-color: #00af00\">9,241,705,984</span> │ padding_mask[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>],        │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">GemmaBackbone</span>)               │                           │                 │ token_ids[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>]            │\n",
              "├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤\n",
              "│ token_embedding               │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">256000</span>)      │     <span style=\"color: #00af00; text-decoration-color: #00af00\">917,504,000</span> │ gemma_backbone[<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>][<span style=\"color: #00af00; text-decoration-color: #00af00\">0</span>]       │\n",
              "│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">ReversibleEmbedding</span>)         │                           │                 │                            │\n",
              "└───────────────────────────────┴───────────────────────────┴─────────────────┴────────────────────────────┘\n",
              "</pre>\n"
            ],
            "text/plain": [
              "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n",
              "┃\u001b[1m \u001b[0m\u001b[1mLayer (type)                 \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape             \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m        Param #\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mConnected to              \u001b[0m\u001b[1m \u001b[0m┃\n",
              "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩\n",
              "│ padding_mask (\u001b[38;5;33mInputLayer\u001b[0m)     │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;45mNone\u001b[0m)              │               \u001b[38;5;34m0\u001b[0m │ -                          │\n",
              "├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤\n",
              "│ token_ids (\u001b[38;5;33mInputLayer\u001b[0m)        │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;45mNone\u001b[0m)              │               \u001b[38;5;34m0\u001b[0m │ -                          │\n",
              "├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤\n",
              "│ gemma_backbone                │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m3584\u001b[0m)        │   \u001b[38;5;34m9,241,705,984\u001b[0m │ padding_mask[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m],        │\n",
              "│ (\u001b[38;5;33mGemmaBackbone\u001b[0m)               │                           │                 │ token_ids[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m]            │\n",
              "├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤\n",
              "│ token_embedding               │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m256000\u001b[0m)      │     \u001b[38;5;34m917,504,000\u001b[0m │ gemma_backbone[\u001b[38;5;34m0\u001b[0m][\u001b[38;5;34m0\u001b[0m]       │\n",
              "│ (\u001b[38;5;33mReversibleEmbedding\u001b[0m)         │                           │                 │                            │\n",
              "└───────────────────────────────┴───────────────────────────┴─────────────────┴────────────────────────────┘\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Total params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">9,241,705,984</span> (17.21 GB)\n",
              "</pre>\n"
            ],
            "text/plain": [
              "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m9,241,705,984\u001b[0m (17.21 GB)\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">9,241,705,984</span> (17.21 GB)\n",
              "</pre>\n"
            ],
            "text/plain": [
              "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m9,241,705,984\u001b[0m (17.21 GB)\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Non-trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> (0.00 B)\n",
              "</pre>\n"
            ],
            "text/plain": [
              "\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m0\u001b[0m (0.00 B)\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "import keras_nlp\n",
        "import keras\n",
        "\n",
        "# Run at half precision.\n",
        "keras.config.set_floatx(\"bfloat16\")\n",
        "\n",
        "# using 9B instruction-tuned model\n",
        "gemma_lm = keras_nlp.models.GemmaCausalLM.from_preset(\"gemma2_instruct_9b_en\")\n",
        "gemma_lm.summary()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "CQ837Wrra_d3"
      },
      "source": [
        "### Define formatting helper functions"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {
        "id": "z6nQPPU7bFk6"
      },
      "outputs": [],
      "source": [
        "from IPython.display import Markdown\n",
        "import textwrap\n",
        "\n",
        "def display_chat(prompt, text):\n",
        "  formatted_prompt = \"<font size='+1' color='brown'>🙋‍♂️<blockquote>\" + prompt + \"</blockquote></font>\"\n",
        "  text = text.replace('•', '  *')\n",
        "  text = textwrap.indent(text, '> ', predicate=lambda _: True)\n",
        "  formatted_text = \"<font size='+1' color='teal'>🤖\\n\\n\" + text + \"\\n</font>\"\n",
        "  return Markdown(formatted_prompt+formatted_text)\n",
        "\n",
        "def to_markdown(text):\n",
        "  text = text.replace('•', '  *')\n",
        "  return Markdown(textwrap.indent(text, '> ', predicate=lambda _: True))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vro4q-yCbG-f"
      },
      "source": [
        "### Create a chat helper to manage the conversation state"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {
        "id": "O0TkvhOASI9f"
      },
      "outputs": [],
      "source": [
        "class ChatState():\n",
        "  \"\"\"\n",
        "  Manages the conversation history for a turn-based chatbot\n",
        "  Follows the turn-based conversation guidelines for the Gemma family of models\n",
        "  documented at https://ai.google.dev/gemma/docs/formatting\n",
        "  \"\"\"\n",
        "\n",
        "  __START_TURN_USER__ = \"<start_of_turn>user\\n\"\n",
        "  __START_TURN_MODEL__ = \"<start_of_turn>model\\n\"\n",
        "  __END_TURN__ = \"<end_of_turn>\\n\"\n",
        "\n",
        "  def __init__(self, model, system=\"\"):\n",
        "    \"\"\"\n",
        "    Initializes the chat state.\n",
        "\n",
        "    Args:\n",
        "        model: The language model to use for generating responses.\n",
        "        system: (Optional) System instructions or bot description.\n",
        "    \"\"\"\n",
        "    self.model = model\n",
        "    self.system = system\n",
        "    self.history = []\n",
        "\n",
        "  def add_to_history_as_user(self, message):\n",
        "      \"\"\"\n",
        "      Adds a user message to the history with start/end turn markers.\n",
        "      \"\"\"\n",
        "      self.history.append(self.__START_TURN_USER__ + message + self.__END_TURN__)\n",
        "\n",
        "  def add_to_history_as_model(self, message):\n",
        "      \"\"\"\n",
        "      Adds a model response to the history with the start turn marker.\n",
        "      Model will generate end turn marker.\n",
        "      \"\"\"\n",
        "      self.history.append(self.__START_TURN_MODEL__ + message)\n",
        "\n",
        "  def get_history(self):\n",
        "      \"\"\"\n",
        "      Returns the entire chat history as a single string.\n",
        "      \"\"\"\n",
        "      return \"\".join([*self.history])\n",
        "\n",
        "  def get_full_prompt(self):\n",
        "    \"\"\"\n",
        "    Builds the prompt for the language model, including history and system description.\n",
        "    \"\"\"\n",
        "    prompt = self.get_history() + self.__START_TURN_MODEL__\n",
        "    if len(self.system)>0:\n",
        "      prompt = self.system + \"\\n\" + prompt\n",
        "    return prompt\n",
        "\n",
        "  def send_message(self, message):\n",
        "    \"\"\"\n",
        "    Handles sending a user message and getting a model response.\n",
        "\n",
        "    Args:\n",
        "        message: The user's message.\n",
        "\n",
        "    Returns:\n",
        "        The model's response.\n",
        "    \"\"\"\n",
        "    self.add_to_history_as_user(message)\n",
        "    prompt = self.get_full_prompt()\n",
        "    response = self.model.generate(prompt, max_length=4096)\n",
        "    result = response.replace(prompt, \"\")  # Extract only the new response\n",
        "    self.add_to_history_as_model(result)\n",
        "    return result\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "52Ell80sbRmy"
      },
      "source": [
        "### Chat with the model"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {
        "id": "shfCZDFPKghT"
      },
      "outputs": [
        {
          "data": {
            "text/markdown": "<font size='+1' color='brown'>🙋‍♂️<blockquote>help me understand how to make coffee</blockquote></font><font size='+1' color='teal'>🤖\n\n> ##  Let's Brew Some Coffee! ☕️\n> \n> Making coffee can be as simple or complex as you like. Here's a breakdown of some popular methods, from beginner-friendly to more advanced:\n> \n> **1. The Quick & Easy: Instant Coffee**\n> \n> * **What you need:** Instant coffee granules, hot water\n> * **How to:** Simply add a spoonful of instant coffee to a mug, pour hot water over it, stir, and enjoy!\n> \n> **2. The Classic: Drip Coffee Maker**\n> \n> * **What you need:** Drip coffee maker, ground coffee, filter\n> * **How to:**\n>     * Fill the water reservoir with fresh, cold water.\n>     * Place a filter in the filter basket.\n>     * Add the desired amount of ground coffee to the filter.\n>     * Turn on the coffee maker and let it do its thing!\n> \n> **3. The French Press:**\n> \n> * **What you need:** French press, coarse ground coffee, hot water\n> * **How to:**\n>     * Add coarse ground coffee to the French press.\n>     * Pour hot water (just off the boil) over the coffee grounds.\n>     * Stir gently and let it steep for 4 minutes.\n>     * Slowly press the plunger down to separate the grounds from the coffee.\n>     * Pour and enjoy!\n> \n> **4. The Pour Over:**\n> \n> * **What you need:** Pour over cone, filter, medium-fine ground coffee, hot water\n> * **How to:**\n>     * Place a filter in the cone and rinse it with hot water to remove any paper taste.\n>     * Add medium-fine ground coffee to the filter.\n>     * Slowly pour hot water over the grounds in a circular motion, ensuring all grounds are saturated.\n>     * Let the coffee drip through into your cup.\n> \n> **5. The Espresso Machine:**\n> \n> * **What you need:** Espresso machine, finely ground coffee, tamper\n> * **How to:**\n>     * Grind your coffee beans finely.\n>     * Tamp the coffee grounds firmly into the portafilter.\n>     * Lock the portafilter into the espresso machine.\n>     * Brew your espresso shot!\n> \n> **Tips for Delicious Coffee:**\n> \n> * **Use fresh, quality beans:** The better the beans, the better the coffee.\n> * **Grind your beans right before brewing:** This preserves freshness and flavor.\n> * **Use filtered water:** Impurities in water can affect the taste of your coffee.\n> * **Experiment with different brewing methods:** Find what you like best!\n> * **Don't be afraid to adjust:** Play with the amount of coffee, water, and brewing time to find your perfect cup.\n> \n> \n> Let me know if you have any other questions or want to explore a specific brewing method in more detail!<end_of_turn>\n\n</font>",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "chat = ChatState(gemma_lm)\n",
        "message = \"help me understand how to make coffee\"\n",
        "display_chat(message, chat.send_message(message))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {
        "id": "bLxtlhjtLkWQ"
      },
      "outputs": [
        {
          "data": {
            "text/markdown": "<font size='+1' color='brown'>🙋‍♂️<blockquote>what is the best coffee?</blockquote></font><font size='+1' color='teal'>🤖\n\n> Ah, the eternal question! There's no single \"best\" coffee because taste is subjective. What one person finds delicious, another might find bitter or bland. \n> \n> It all depends on your personal preferences:\n> \n> **Consider these factors:**\n> \n> * **Roast Level:**\n>     * **Light:** Bright acidity, delicate flavors, often fruity or floral.\n>     * **Medium:** Balanced acidity and body, with more pronounced flavors.\n>     * **Dark:** Bold, smoky, sometimes bittersweet, with less acidity.\n> * **Origin:** Different regions produce beans with unique flavor profiles:\n>     * **Latin America:** Often chocolatey, nutty, with medium acidity.\n>     * **Africa:** Known for bright acidity, fruity notes, and floral aromas.\n>     * **Asia/Pacific:** Earthy, spicy, sometimes with chocolate or caramel notes.\n> * **Brewing Method:**  The method you use can significantly impact the flavor.\n> \n> **Some Popular and Highly-Regarded Coffees:**\n> \n> * **Ethiopian Yirgacheffe:** Known for its floral, citrusy, and tea-like qualities.\n> * **Kenyan AA:** Bright acidity, black currant, and berry flavors.\n> * **Sumatran Mandheling:** Earthy, spicy, with low acidity.\n> * **Colombian Supremo:** Balanced, with chocolate and caramel notes.\n> \n> **My Recommendation:**\n> \n> * **Start exploring!** Try different roasts, origins, and brewing methods to discover what you enjoy most.\n> * **Talk to your local coffee shop:** Baristas are passionate about coffee and can offer great recommendations based on your preferences.\n> * **Don't be afraid to experiment:**  The world of coffee is vast and exciting!\n> \n> \n> Happy brewing!<end_of_turn>\n\n</font>",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "message = \"what is the best coffee?\"\n",
        "display_chat(message, chat.send_message(message))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "metadata": {
        "id": "tfvgl4sC9g2p"
      },
      "outputs": [
        {
          "data": {
            "text/markdown": "<font size='+1' color='brown'>🙋‍♂️<blockquote>what are similar drinks?</blockquote></font><font size='+1' color='teal'>🤖\n\n> You're looking for drinks that share similarities with coffee! Here are some options, categorized by what aspect of coffee they resemble:\n> \n> **Similar Caffeine Kick:**\n> \n> * **Tea:**  Comes in endless varieties, with varying caffeine levels. Black tea has the most caffeine, followed by green, white, and herbal teas.\n> * **Matcha:** A powdered green tea with a unique earthy flavor and a good amount of caffeine.\n> * **Yerba Mate:** A South American beverage with a slightly bitter, grassy flavor and a caffeine boost comparable to coffee.\n> \n> **Similar Rich, Roasted Flavor:**\n> \n> * **Chicory Coffee:** Made from roasted chicory root, it has a coffee-like flavor but is caffeine-free.\n> * **Roasted Barley Tea:**  A caffeine-free option with a nutty, roasted flavor.\n> \n> **Similar Creamy, Indulgent Experience:**\n> \n> * **Hot Chocolate:**  A classic comfort drink with a rich, chocolatey flavor.\n> * **Golden Milk:** A warming drink made with turmeric, ginger, cinnamon, and milk.\n> \n> **Similar Ritual and Experience:**\n> \n> * **Chai Tea Latte:** A spiced black tea latte with a creamy, comforting flavor.\n> * **London Fog:** A blend of Earl Grey tea, steamed milk, and vanilla syrup.\n> \n> **Beyond the Usual:**\n> \n> * **Kava:** A Polynesian drink made from the kava root, known for its relaxing and social effects.\n> * **Guayusa:** A South American tea with a smooth, slightly sweet flavor and a moderate caffeine boost.\n> \n> \n> Remember, taste is subjective! Explore these options and see what you enjoy most.<end_of_turn>\n\n</font>",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "message = \"what are similar drinks?\"\n",
        "display_chat(message, chat.send_message(message))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Y85tod32c7lA"
      },
      "source": [
        "Use the `get_history` method to see how all the context was retained by the Chat class."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "metadata": {
        "id": "P2GjAVybBez3"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "<start_of_turn>user\n",
            "help me understand how to make coffee<end_of_turn>\n",
            "<start_of_turn>model\n",
            "##  Let's Brew Some Coffee! ☕️\n",
            "\n",
            "Making coffee can be as simple or complex as you like. Here's a breakdown of some popular methods, from beginner-friendly to more advanced:\n",
            "\n",
            "**1. The Quick & Easy: Instant Coffee**\n",
            "\n",
            "* **What you need:** Instant coffee granules, hot water\n",
            "* **How to:** Simply add a spoonful of instant coffee to a mug, pour hot water over it, stir, and enjoy!\n",
            "\n",
            "**2. The Classic: Drip Coffee Maker**\n",
            "\n",
            "* **What you need:** Drip coffee maker, ground coffee, filter\n",
            "* **How to:**\n",
            "    * Fill the water reservoir with fresh, cold water.\n",
            "    * Place a filter in the filter basket.\n",
            "    * Add the desired amount of ground coffee to the filter.\n",
            "    * Turn on the coffee maker and let it do its thing!\n",
            "\n",
            "**3. The French Press:**\n",
            "\n",
            "* **What you need:** French press, coarse ground coffee, hot water\n",
            "* **How to:**\n",
            "    * Add coarse ground coffee to the French press.\n",
            "    * Pour hot water (just off the boil) over the coffee grounds.\n",
            "    * Stir gently and let it steep for 4 minutes.\n",
            "    * Slowly press the plunger down to separate the grounds from the coffee.\n",
            "    * Pour and enjoy!\n",
            "\n",
            "**4. The Pour Over:**\n",
            "\n",
            "* **What you need:** Pour over cone, filter, medium-fine ground coffee, hot water\n",
            "* **How to:**\n",
            "    * Place a filter in the cone and rinse it with hot water to remove any paper taste.\n",
            "    * Add medium-fine ground coffee to the filter.\n",
            "    * Slowly pour hot water over the grounds in a circular motion, ensuring all grounds are saturated.\n",
            "    * Let the coffee drip through into your cup.\n",
            "\n",
            "**5. The Espresso Machine:**\n",
            "\n",
            "* **What you need:** Espresso machine, finely ground coffee, tamper\n",
            "* **How to:**\n",
            "    * Grind your coffee beans finely.\n",
            "    * Tamp the coffee grounds firmly into the portafilter.\n",
            "    * Lock the portafilter into the espresso machine.\n",
            "    * Brew your espresso shot!\n",
            "\n",
            "**Tips for Delicious Coffee:**\n",
            "\n",
            "* **Use fresh, quality beans:** The better the beans, the better the coffee.\n",
            "* **Grind your beans right before brewing:** This preserves freshness and flavor.\n",
            "* **Use filtered water:** Impurities in water can affect the taste of your coffee.\n",
            "* **Experiment with different brewing methods:** Find what you like best!\n",
            "* **Don't be afraid to adjust:** Play with the amount of coffee, water, and brewing time to find your perfect cup.\n",
            "\n",
            "\n",
            "Let me know if you have any other questions or want to explore a specific brewing method in more detail!<end_of_turn>\n",
            "<start_of_turn>user\n",
            "what is the best coffee?<end_of_turn>\n",
            "<start_of_turn>model\n",
            "Ah, the eternal question! There's no single \"best\" coffee because taste is subjective. What one person finds delicious, another might find bitter or bland. \n",
            "\n",
            "It all depends on your personal preferences:\n",
            "\n",
            "**Consider these factors:**\n",
            "\n",
            "* **Roast Level:**\n",
            "    * **Light:** Bright acidity, delicate flavors, often fruity or floral.\n",
            "    * **Medium:** Balanced acidity and body, with more pronounced flavors.\n",
            "    * **Dark:** Bold, smoky, sometimes bittersweet, with less acidity.\n",
            "* **Origin:** Different regions produce beans with unique flavor profiles:\n",
            "    * **Latin America:** Often chocolatey, nutty, with medium acidity.\n",
            "    * **Africa:** Known for bright acidity, fruity notes, and floral aromas.\n",
            "    * **Asia/Pacific:** Earthy, spicy, sometimes with chocolate or caramel notes.\n",
            "* **Brewing Method:**  The method you use can significantly impact the flavor.\n",
            "\n",
            "**Some Popular and Highly-Regarded Coffees:**\n",
            "\n",
            "* **Ethiopian Yirgacheffe:** Known for its floral, citrusy, and tea-like qualities.\n",
            "* **Kenyan AA:** Bright acidity, black currant, and berry flavors.\n",
            "* **Sumatran Mandheling:** Earthy, spicy, with low acidity.\n",
            "* **Colombian Supremo:** Balanced, with chocolate and caramel notes.\n",
            "\n",
            "**My Recommendation:**\n",
            "\n",
            "* **Start exploring!** Try different roasts, origins, and brewing methods to discover what you enjoy most.\n",
            "* **Talk to your local coffee shop:** Baristas are passionate about coffee and can offer great recommendations based on your preferences.\n",
            "* **Don't be afraid to experiment:**  The world of coffee is vast and exciting!\n",
            "\n",
            "\n",
            "Happy brewing!<end_of_turn>\n",
            "<start_of_turn>user\n",
            "what are similar drinks?<end_of_turn>\n",
            "<start_of_turn>model\n",
            "You're looking for drinks that share similarities with coffee! Here are some options, categorized by what aspect of coffee they resemble:\n",
            "\n",
            "**Similar Caffeine Kick:**\n",
            "\n",
            "* **Tea:**  Comes in endless varieties, with varying caffeine levels. Black tea has the most caffeine, followed by green, white, and herbal teas.\n",
            "* **Matcha:** A powdered green tea with a unique earthy flavor and a good amount of caffeine.\n",
            "* **Yerba Mate:** A South American beverage with a slightly bitter, grassy flavor and a caffeine boost comparable to coffee.\n",
            "\n",
            "**Similar Rich, Roasted Flavor:**\n",
            "\n",
            "* **Chicory Coffee:** Made from roasted chicory root, it has a coffee-like flavor but is caffeine-free.\n",
            "* **Roasted Barley Tea:**  A caffeine-free option with a nutty, roasted flavor.\n",
            "\n",
            "**Similar Creamy, Indulgent Experience:**\n",
            "\n",
            "* **Hot Chocolate:**  A classic comfort drink with a rich, chocolatey flavor.\n",
            "* **Golden Milk:** A warming drink made with turmeric, ginger, cinnamon, and milk.\n",
            "\n",
            "**Similar Ritual and Experience:**\n",
            "\n",
            "* **Chai Tea Latte:** A spiced black tea latte with a creamy, comforting flavor.\n",
            "* **London Fog:** A blend of Earl Grey tea, steamed milk, and vanilla syrup.\n",
            "\n",
            "**Beyond the Usual:**\n",
            "\n",
            "* **Kava:** A Polynesian drink made from the kava root, known for its relaxing and social effects.\n",
            "* **Guayusa:** A South American tea with a smooth, slightly sweet flavor and a moderate caffeine boost.\n",
            "\n",
            "\n",
            "Remember, taste is subjective! Explore these options and see what you enjoy most.<end_of_turn>\n",
            "\n"
          ]
        }
      ],
      "source": [
        "print(chat.get_history())"
      ]
    }
  ],
  "metadata": {
    "accelerator": "GPU",
    "colab": {
      "name": "Keras_Gemma_2_Quickstart_Chat.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
